package com.ada.sqlSession;

import com.ada.pojo.Configuration;
import com.ada.pojo.MappedStatement;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    private SimpleExecutor executor;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
        executor = new SimpleExecutor();
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {
        //SimpleExecutor的query方法的调用
        List<Object> list = executor.query(configuration, configuration.getMappedStatementMap().get(statementId), params);
        return (List<E>) list;
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        List<Object> objects = selectList(statementId, params);
        if (objects.size() == 1) {
            return (T) objects.get(0);
        } else {
            throw new RuntimeException("查询结果为空或者返回结果过多");
        }
    }

    //使用jdk动态代理为Dao接口生成代理对象
    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //准备参数 statementId sql语句的唯一标识，namespace.id=接口全限定名.方法名
                // findAll
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String statementId = className + "." + methodName;
                OperationType operationType = configuration.getMappedStatementMap().get(statementId).getOperationType();
                if(operationType == null){
                    throw new RuntimeException("不支持的操作!");
                }
                switch (operationType){
                    case SELECT:{
                        //获取被调用方法的返回类型
                        Type genericReturnType = method.getGenericReturnType();
                        //判断是否进行了泛型类型参数化
                        if (genericReturnType instanceof ParameterizedType) {
                            return selectList(statementId, args);
                        }
                        return selectOne(statementId, args);
                    }
                    case INSERT:{
                        return insert(statementId,args);
                    }
                    case UPDATE:{
                        return update(statementId,args);
                    }
                    case DELETE:{
                        return update(statementId,args);
                    }
                    default:
                        throw new RuntimeException("不支持的操作!");
                }

                //准备参数2 params：args


            }
        });
        return (T) o;
    }


    @Override
    public int insert(String statement, Object... params) throws Exception{
        return update(statement,params);
    }

    @Override
    public int update(String statementId, Object... params) throws Exception {
        return executor.update(configuration, configuration.getMappedStatementMap().get(statementId), params);
    }

    @Override
    public int delete(String statement, Object... params) throws Exception{
        return update(statement,params);
    }
}
